#include "Mutex.hh"

Mutex::Mutex()
{
	State = false;
	Locked = false;
	
	ResultOf Result;
	Result = initMutexObj();
	checkErrorFV(Result, "Fail init.");
	
	State = true;
}

Mutex::~Mutex()
{
	ResultOf Result;
	Result = destroyMutexObj();
	checkErrorWOR(Result, "Fail destroy.");
}

ResultOf Mutex::lock()
{
	if (!State)
	{
		fprintf(stderr, "This instance(%x) is not available.\n", (Number)this);
		return RETURN_ERROR;
	}
	
	ResultOf Result;
	Result = pthread_mutex_lock(&MutexObj);
	checkErrorWR(Result, "Fail pthread_mutex_lock.");
	
	return RETURN_OK;
}

ResultOf Mutex::lockReadOnly()
{
	if (!State)
	{
		fprintf(stderr, "This instance(%x) is not available.\n", (Number)this);
		return RETURN_ERROR;
	}
	
	return RETURN_ERROR;
}

ResultOf Mutex::unlock()
{
	if (!State)
	{
		fprintf(stderr, "This instance(%x) is not available.\n", (Number)this);
		return RETURN_ERROR;
	}
	
	ResultOf Result;
	Result = pthread_mutex_unlock(&MutexObj);
	checkErrorWR(Result, "Fail pthread_mutex_unlock.");
	
	return RETURN_OK;
}

ResultOf Mutex::initMutexObj()
{
	ResultOf Result;
	Result = pthread_mutex_init(&MutexObj, NULL);
	checkErrorWR(Result, "Fail pthread_mutex_init.");
	
	return RETURN_OK;
}

ResultOf Mutex::destroyMutexObj()
{
	ResultOf Result;
	ResultOf Result2;
	
	while ((Result = pthread_mutex_destroy(&MutexObj)) == RETURN_BUSY)
	{
		Result2 = lock();
		checkErrorWR(Result2, "Fail lock.");
		
		Result2 = unlock();
		checkErrorWR(Result2, "Fail unlock.");
	}
	
	if (checkError(Result) && Result != RETURN_BUSY)
	{
		notifyError(Result, "Fail pthread_mutex_destroy.");
		return RETURN_ERROR;
	}
	
	return RETURN_OK;
}

pthread_mutex_t* Mutex::tellObj()
{
	return &MutexObj;
}
